﻿/*************************************************************************************

- CLR版本：        4.0.30319.42000
- 类 名 称：       SocketClientHelper
- 机器名称：       YTE
- 命名空间：       Common
- 文 件 名：       SocketClientHelper
- 创建时间：       2021/1/8 21:16:02
- 作    者：       YTE
- 说   明：
- 修改时间：
- 修 改 人：
  *************************************************************************************/

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using YTE;

namespace Client.Utils
{
    public class SocketClientHelper
    {
        public Action<SendType, string> ReciveAction;
        public Action<string> LogAction;
        public Action<string, int, long> ReciveProgressAction;
        public Action<bool> ConnectAction;

        private Socket ClientSocket;
        private string ServerIp;
        private int Port;
        private string SaveFilePath;
        public bool IsConnect { get; private set; } = false;
        public Socket GetSocket
        {
            get
            {
                return ClientSocket;
            }
        }
        public SocketClientHelper(string serverIp, int port, string saveFilePath)
        {
            ServerIp = serverIp;
            Port = port;
            SaveFilePath = saveFilePath;
        }

        /// <summary>
        /// 启动连接
        /// </summary>
        public void Start()
        {
            try
            {
                //创建负责通信的Socket
                ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //获取服务端的IP
                IPAddress ip = IPAddress.Parse(ServerIp);
                //获取服务端的端口号
                IPEndPoint port = new IPEndPoint(ip, Port);
                //获得要连接的远程服务器应用程序的IP地址和端口号
                ClientSocket.Connect(port);
                LogAction?.Invoke("连接成功");
                ConnectAction?.Invoke(true);
                IsConnect = true;
                //新建线程，去接收客户端发来的信息
                Thread td = new Thread(AcceptMgs);
                td.IsBackground = true;
                td.Start();
            }
            catch (Exception ex)
            {
                LogAction?.Invoke(ex.Message);
            }
        }
        /// <summary>
        /// 发送字符串
        /// </summary>
        /// <param name="msg"></param>
        public void Send(string msg)
        {
            if (!IsConnect)
            {
                LogAction?.Invoke("未连接");
                return;
            }
            byte[] buffer = Encoding.UTF8.GetBytes(msg);
            List<byte> byteList = new List<byte>();
            byteList.Add((int)SendType.字符串);
            byteList.AddRange(buffer.ToArray());

            ClientSocket.Send(byteList.ToArray());
        }
        /// <summary>
        /// 发送对象
        /// </summary>
        /// <param name="msg"></param>
        public void SendObject(string msg)
        {
            if (!IsConnect)
            {
                LogAction?.Invoke("未连接");
                return;
            }
            byte[] buffer = Encoding.UTF8.GetBytes(msg);
            List<byte> byteList = new List<byte>();
            byteList.Add((int)SendType.对象);
            byteList.AddRange(buffer.ToArray());

            ClientSocket.Send(byteList.ToArray());
        }
        /// <summary>
        /// 接收数据
        /// </summary>
        private void AcceptMgs()
        {
            long length = 0;
            string filePath = string.Empty;
            int receivLen = 0;
            long fileLen = 0;
            while (true)
            {
                byte[] buffer = new byte[1024 * 1024 * 5];
                int r = 0;
                try
                {
                    r = ClientSocket.Receive(buffer);
                }
                catch (Exception)
                {
                    IsConnect = false;
                    ConnectAction?.Invoke(false);
                    LogAction?.Invoke("与服务器连接中断");
                    return;
                }
                if (r == 0)
                {
                    break;
                }

                if (buffer[0] == (int)SendType.字符串)
                {
                    string strMsg = Encoding.UTF8.GetString(buffer, 1, r - 1);
                    ReciveAction?.Invoke(SendType.字符串, strMsg);
                }
                else if (buffer[0] == (int)SendType.文件)
                {
                    try
                    {
                        string strMsg = Encoding.UTF8.GetString(buffer, 1, r - 1);
                        string[] strs = strMsg.Split('-');
                        string fileName = strs[0];
                        length = long.Parse(strs[1]);
                        fileLen = length;
                        receivLen = 0;
                        filePath = Path.Combine(SaveFilePath, fileName);
                        using (FileStream MyFileStream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite))
                        {
                            if (length > 0)
                            {
                                while (true)
                                {
                                    r = ClientSocket.Receive(buffer);
                                    MyFileStream.Write(buffer, 0, r);
                                    length -= r; //减去每次保存的字节数
                                    receivLen += r;
                                    ReciveProgressAction?.Invoke(fileName, receivLen, fileLen);
                                    if (length == 0)
                                    {
                                        LogAction?.Invoke($"{fileName}:接收文件成功");
                                        break;
                                    }
                                    //Thread.Sleep(300);
                                }

                                MyFileStream.Close();
                                MyFileStream.Dispose();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }

                }
                else if (buffer[0] == (int)SendType.对象)
                {
                    string strMsg = Encoding.UTF8.GetString(buffer, 1, r - 1);
                    ReciveAction?.Invoke(SendType.对象, strMsg);
                }
            }
        }
    }

}
